using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using OFX.Aggregator.Infrastructure;

namespace OFX.Aggregator.Implementation
{
	public class StatementXmlToOFXConverter : IStatementOfxConverter
	{
		private readonly string ofxXsltFilePath;

		public StatementXmlToOFXConverter(string ofxXsltFilePath)
		{
			this.ofxXsltFilePath = ofxXsltFilePath;
		}

		#region IStatementOfxConverter Members

		public Stream ConvertToOfx(Stream inputStream)
		{
			Stream outputStream;

			inputStream.Seek(0, SeekOrigin.Begin);

			var xmlReader = new XmlTextReader(inputStream);

			var xslt = new XslCompiledTransform();
			xslt.Load(this.ofxXsltFilePath);

			var xpathDoc = new XPathDocument(xmlReader);

			for (;;)
			{
				string tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
				tempFilePath = Path.ChangeExtension(tempFilePath, ".ofx");
				if (!File.Exists(tempFilePath))
				{
					try
					{
						outputStream = new FileStream(tempFilePath, FileMode.CreateNew,
						                              FileAccess.ReadWrite, FileShare.Read, 4096,
						                              FileOptions.SequentialScan);
						using (var textWriter = new StreamWriter(outputStream, Encoding.UTF8, 4096))
						{
							xslt.Transform(xpathDoc, null, textWriter);
						}

#if DEBUG
						string ofx = new StreamReader(tempFilePath).ReadToEnd();
						Debug.Write(ofx);
#endif

						break;
					}
					catch (IOException)
					{
						continue; // This filename already exists
					}
				}
			}

			return outputStream;
		}

		#endregion
	}
}